package gameservice

import (
	"fmt"
	"gogame/gameconfig"
	"gogame/gameservice/service"
	"gogame/lib"
	"gogame/logger"
	"os"
	"os/signal"
	"runtime/debug"
	"strings"
	"sync"
	"syscall"
)

var (
	SigEvent        = lib.NewEventEmitter()                        // 信号事件监听
	serviceMap      = make(map[string]map[string]service.IService) // service类型对应的所有service
	Service2NewFunc = make(map[string]func() service.IService)     // service创建func
)

func init() {
	go Notify()
}

// Notify 监听服务中止
func Notify() {
	sigChan := make(chan os.Signal)
	signal.Notify(
		sigChan,
		os.Interrupt,    //退出信号 ctrl+c退出
		os.Kill,         //kill 信号
		syscall.SIGHUP,  //终端控制进程结束(终端连接断开)
		syscall.SIGINT,  //用户发送INTR字符(Ctrl+C)触发
		syscall.SIGTERM, //结束程序(可以被捕获、阻塞或忽略)
		syscall.SIGQUIT, //用户发送QUIT字符(Ctrl+/)触发
	)
	sig := <-sigChan
	close(sigChan)
	fmt.Println()

	// 广播服务中止
	SigEvent.Emit("SIG", sig)
}

func FmtKey(serviceType, serviceListen string) string {
	return fmt.Sprintf("%s_%s", serviceType, serviceListen)
}

// 是否本机ip
func isLocalIp(address string) bool {
	if address != gameconfig.ServerConfig.LocalIp {
		return false
	}

	return true
}

func _startService(service service.IService, serviceType, listen string) {
	Register(service, serviceType, listen)
	StartService(serviceType, listen)
}

// RunGateway 启动gateway
func RunGateway() {
	_serviceType := "gateway"
	for _, listen := range gameconfig.ServerConfig.Gateway {
		address := strings.Split(listen, ":")
		// 只启动本机ip
		if !isLocalIp(address[0]) {
			continue
		}
		_startService(
			Service2NewFunc[_serviceType](),
			_serviceType,
			listen,
		)
	}
}

// RunWorker 启动worker
func RunWorker() {
	_serviceType := "worker"
	for _, listen := range gameconfig.ServerConfig.Worker {
		address := strings.Split(listen, ":")
		// 只启动本机ip
		if !isLocalIp(address[0]) {
			continue
		}
		_startService(
			Service2NewFunc[_serviceType](),
			_serviceType,
			listen,
		)
	}

}

// RunModelLog 启动modelLog
func RunModelLog() {
	_serviceType, listen := "modellog", "-1"
	_startService(
		Service2NewFunc[_serviceType](),
		_serviceType,
		listen,
	)
}

// RunTimer 启动定时器
func RunTimer() {
	_service := Service2NewFunc["timer"]()
	_serviceType, listen := "timer", _service.GetTag()
	_startService(
		_service,
		_serviceType,
		listen,
	)

}

// Register 服务注册
func Register(s service.IService, serviceType, serviceListen string) {
	s.SetName(FmtKey(serviceType, serviceListen))
	s.SetListen(serviceListen)

	_, ok := serviceMap[serviceType]
	if !ok {
		serviceMap[serviceType] = make(map[string]service.IService)
	}
	serviceMap[serviceType][serviceListen] = s
}

// GetService 获取服务
func GetService(serviceType, serviceListen string) service.IService {
	_serviceListen2Service := serviceMap[serviceType]

	// 服务不存在
	if _serviceListen2Service == nil {
		logger.Print("serviceType no exists %s", serviceType)
		return nil
	}

	_service, _ok := _serviceListen2Service[serviceListen]
	if !_ok {
		logger.Print("serviceType %s no exists listen %s", serviceType, serviceListen)
		return nil
	}
	return _service
}

// GetServiceListByType 获取某一类服务list
func GetServiceListByType(serviceType string) []service.IService {
	_listen2Service := serviceMap[serviceType]

	// 服务不存在
	if _listen2Service == nil {
		logger.Print("serviceType no exists %s", serviceType)
		return nil
	}

	_serviceList := make([]service.IService, 0)
	for _, service := range _listen2Service {
		_serviceList = append(_serviceList, service)
	}

	return _serviceList
}

// GetServiceByRand 随机取一个x类服务
func GetServiceByRand(serviceType string) service.IService {
	_serviceList := GetServiceListByType(serviceType)

	// 服务不存在
	if _serviceList == nil {
		return nil
	}

	if len(_serviceList) == 1 {
		return _serviceList[0]
	} else {
		_randIdx := lib.Rand.RandInt(0, len(_serviceList))
		return _serviceList[_randIdx]
	}

}

// GetServiceByRand2Worker 随机取一个worker服务
func GetServiceByRand2Worker() service.IService {
	_service := GetServiceByRand("worker")

	// 服务不存在
	if _service == nil {
		return nil
	}

	return _service
}

// StartService 开启服务
func StartService(serviceType, serviceListen string) {
	defer func() {
		if r := recover(); r != nil {
			errMsg := fmt.Sprintf(
				"servicemanage.StartService error!!\nserviceType:【%s】 serviceListen: 【%s】\nerr--->: 【%s】\n%s\n",
				serviceType,
				serviceListen,
				r.(error).Error(),
				debug.Stack(),
			)
			logger.EasyLog.Error(errMsg)
		}
	}()
	_service := GetService(serviceType, serviceListen)

	// 服务不存在
	if _service == nil {
		logger.Print("service no exists %s", FmtKey(serviceType, serviceListen))
		return
	}

	// 退出信号监听
	SigEvent.On("SIG", func(sig syscall.Signal) {
		StopService(serviceType, serviceListen)
	})

	_service.Start(_service)
}

// StopService 停止服务
func StopService(serviceType, serviceListen string) {
	defer func() {
		if r := recover(); r != nil {
			errMsg := fmt.Sprintf(
				"StopService fail!!\nerr--->: 【%s】\n%s\n",
				r.(error).Error(),
				debug.Stack(),
			)
			logger.EasyLog.Warn(errMsg)
		}
	}()

	_service := GetService(serviceType, serviceListen)

	// 服务不存在
	if _service == nil {
		logger.Print("service no exists %s", FmtKey(serviceType, serviceListen))
		return
	}

	// 服务已停止
	if _service.Status() == service.Stop {
		logger.Print("service %s have stop", FmtKey(serviceType, serviceListen))
		return
	}

	_service.Stop(_service)
}

// WaitStop wait服务
func WaitStop() {
	wg := &sync.WaitGroup{}
	for _, listen2s := range serviceMap {
		for _, s := range listen2s {
			wg.Add(1)
			go s.Wait(wg)
		}
	}
	wg.Wait()
}
